/**
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 2010  Sean Beecroft

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

 * @version 1.10 2010-01-01
 * @author Sean Beecroft
 */
package yawiki.server.parsers;

import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import yawiki.server.filters.*;
import yawiki.server.application.*;
import yawiki.server.util.StringUtility;
import yawiki.server.util.Toolbox;

public class Parser {

    public static String parseRedirect(String wikiText) {
        try {
            int justInCase = 0;

            do {

                int bptr = wikiText.indexOf("[[");
                int cnt = 0;
                String middleText = "";

                if (bptr != -1) {
                    for (int i = bptr; i < wikiText.length(); i++) {
                        char c = wikiText.charAt(i);

                        if (c == '[') {
                            cnt++;
                        } else if (c == ']') {
                            cnt--;
                        } else {
                            middleText += c;
                        }

                        if (cnt == 0) {

                            String left = wikiText.substring(0, bptr);
                            String right = wikiText.substring(i + 1, wikiText.length());
                            int findx = middleText.indexOf("|");
                            int indx = middleText.lastIndexOf("|");
                            String page = "";

                            if (indx != -1) {

                                int ptr = middleText.indexOf("|");
                                middleText = middleText.substring(indx + 1, middleText.length());
                                page = StringUtility.capitalize(middleText);
                            }

                            if (page.equals("")) {
                                page = StringUtility.capitalize(middleText);
                            }

                            page = URLEncoder.encode(page, "UTF-8");
                            String redirectLink = "http://" + Globals.domain + Globals.context + page;
                            redirectLink = redirectLink.replaceAll(" ", "_");
                            redirectLink = redirectLink.replaceAll("'", "&apos;");
                            System.out.println("REDIRECT:" + redirectLink);
                            return redirectLink;
                        }
                    }
                }
                justInCase++;
                if (justInCase > 300) {
                    System.out.println("PANIC!!");
                    break;
                }
            } while (wikiText.indexOf("[[") != -1);

            return wikiText;

        } catch (Exception ex) {
            System.out.println("Exception occured:" + ex);
            ex.printStackTrace();
        }

        return wikiText;
    }

    public static Enumeration parseISBN(String wikiText) {

        Hashtable books = new Hashtable();

        for (int j = 0; j < wikiText.length(); j++) {
            try {
                int ptr1 = wikiText.indexOf("isbn", j);
                int ptr2 = wikiText.indexOf("ISBN", j);
                int len = 19;
                String isbn = "";

                if (ptr1 != -1) {
                    isbn = wikiText.substring(ptr1, ptr1 + len);
                    j = ptr1;
                }

                if (ptr2 != -1) {
                    isbn = wikiText.substring(ptr2, ptr2 + len);
                    j = ptr2;
                }

                if (ptr2 == -1 && ptr1 == -1) {
                    break;
                }

                String ret = "";
                for (int i = 4; i < isbn.length(); i++) {
                    char c = isbn.charAt(i);

                    if (StringUtility.isAlphaNumeric(c)) {
                        ret += c;
                    } else {
                    }

                }

                if (!ret.equals("")) {
                    if (Toolbox.isISBN(ret)) {
                        if (books.get(ret) == null) {
                            books.put(ret, ret);
                        }
                    }
                } 
            } catch (Exception ex) {
                System.out.println("Exception in parseISBN:" + ex);
            }

        }

        return books.elements();

    }

    public static String parseReferences(String text) {
        int justInCase = 0;
        String fn = "~";
        text = text.replaceAll("<small>", "");
        text = text.replaceAll("</small>", "");

        text = text.replaceAll("<SMALL>", "");
        text = text.replaceAll("</SMALL>", "");

        do {
            String cite = " <A HREF=\"javascript:alert('Citations are currently unavailable.');\"><SUP>" + fn + "</SUP></A>";

            int ptr = text.indexOf("<ref");
            if (ptr != -1) {
                //fn++;
                String left = text.substring(0, ptr);
                String right = text.substring(ptr, text.length());
                String ref = "";
                int endPtr = right.indexOf("/>");
                if (endPtr != -1) {
                    ref = right.substring(0, endPtr + "/>".length());
                    text = left + cite + right.substring(endPtr + "/>".length(), right.length());
                } else {
                    endPtr = right.indexOf("</reference>");
                    if (endPtr != -1) {
                        ref = right.substring(0, endPtr + "</reference>".length());
                        text = left + cite + right.substring(endPtr + "</reference>".length(), right.length());

                        //i = left.length() + endPtr + "</reference>".length();
                    } else {
                        endPtr = right.indexOf("</ref>");
                        if (endPtr != -1) {
                            ref = right.substring(0, endPtr + "</ref>".length());
                            text = left + cite + right.substring(endPtr + "</ref>".length(), right.length());
                        }
                    }
                }
            }

            justInCase++;
            if (justInCase > 200) {
                System.out.println("Panic!");
                break;
            }

        } while (text.indexOf("<ref") != -1);

        return text;
    }

    public static String parse(String text) {
        try {
            text = text.replaceAll("&amp;", "&");
            text = text.replaceAll("&apos;", "'");
            text = text.replaceAll("&gt;", ">");
            text = text.replaceAll("&lt;", "<");

            // NOTE - >
            // Using this is very dangerous. It can and does effect some URLs and many other things.
            // DO NOT DO THIS.

            text = parseReferences(text);

            // <-  NOTE

            String ret = "";
            int starOn = 0;
            boolean controlOn = false;
            int nCount = 0;
            Vector references = new Vector();
            Vector citations = new Vector();
            Vector links = new Vector();
            int level = 0;
            int blockOn = 0;
            int italicOn = 0;
            int boldOn = 0;

            for (int i = 0; i < text.length(); i++) {
                char c = text.charAt(i);
                switch (c) {

                    case ';':
                    case ':':

                        if (text.charAt(i - 1) == ' ' || text.charAt(i - 1) == '\n' || text.charAt(i - 1) == ':') {
                            ret = ret + "<BLOCKQUOTE>";
                            blockOn++;
                        } else {
                            ret += c;
                        }

                        break;
                    case '[':

                        String link = "";
                        level = 0;
                        for (int j = i; j < text.length(); j++) {
                            if (text.charAt(j) == '[') {
                                level++;
                            } else if (text.charAt(j) == ']') {
                                level--;
                            } else {
                                link += text.charAt(j);
                            }
                            if (level == 0) {
                                links.addElement(link);
                                String domain = "http://" + Globals.domain + Globals.context;
                                if (StringUtility.indexOfIgnoreCase(link, "http://") != -1) {
                                    int ptr = link.indexOf(" ");
                                    String fn = "*"; // foot notes!
                                    if (ptr == -1) {
                                        ret += "<A HREF=\"" + link + "\">" + fn + "</A>";
                                    } else {
                                        String right = link.substring(ptr, link.length());
                                        right = right.trim();
                                        link = link.substring(0, ptr);
                                        link = link.trim();

                                        if (Filter.filterLink(link)) {
                                            ret += "<A HREF=\"" + link + "\" ALT=\"" + right + "\">" + right + "</A>";
                                        }
                                    }
                                } else if (StringUtility.indexOfIgnoreCase(link, "Image:") != -1) {
                                    //IMAGE
                                } else if (link.indexOf("|") != -1) {
                                    int ptr = link.indexOf("|");
                                    String page = link.substring(0, ptr);
                                    String right = link.substring(ptr + 1, link.length());
                                    page = page.trim();
                                    right = right.trim();
                                    link = link.trim();
                                    page = page.replaceAll(" ", "_");
                                    page = page.replaceAll("'", "&apos;");
                                    page = StringUtility.capitalize(page);
                                    page = page.trim();
                                    page = URLEncoder.encode(page, "UTF-8");

                                    if (Filter.filterLink(link)) {
                                        ret += "<A HREF=\"" + domain + page + "\">" + right + "</A>";
                                    }
                                } else {
                                    String pageLink = link;
                                    link = link.trim();
                                    link = link.replaceAll(" ", "_");
                                    link = link.replaceAll("'", "&apos;");
                                    link = StringUtility.capitalize(link);
                                    link = link.trim();
                                    link = URLEncoder.encode(link, "UTF-8");

                                    if (Filter.filterLink(link)) {
                                        ret += "<A HREF=\"" + domain + link + "\">" + pageLink + "</A>";
                                    }
                                }
                                i = j;
                                break;
                            }
                        }
                        break;

                    case '\'':
                        if (text.length() > i + 2) {
                            if (text.charAt(i + 1) == '\'' && text.charAt(i + 2) == '\'') {
                                if (boldOn == 0) {
                                    boldOn++;
                                    i += 2;
                                    ret += "<B>";
                                } else {
                                    boldOn--;
                                    i += 2;
                                    ret += "</B>";

                                }
                            } else if (text.charAt(i + 1) == '\'') {
                                if (italicOn == 0) {
                                    italicOn++;
                                    i += 1;
                                    ret += "<I>";
                                } else {
                                    italicOn--;
                                    i += 1;
                                    ret += "</I>";
                                }

                            } else {
                                ret += '\'';
                            }
                        }

                        break;
                    case '*':
                    case '#':
                        ret = ret + "<UL><IL>";
                        starOn++;
                        break;
                    case ' ':
                        ret += " ";
                        break;

                    case '\n':
                        if (blockOn > 0) {
                            for (int h = 0; h < blockOn; h++) {
                                ret = ret + "</BLOCKQUOTE>\n";
                            }
                            blockOn = 0;
                        }

                        if (italicOn > 0) {
                            for (int h = 0; h < italicOn; h++) {
                                ret = ret + "</I>\n";
                            }
                            italicOn = 0;
                        }
                        if (boldOn > 0) {
                            for (int h = 0; h < boldOn; h++) {
                                ret = ret + "</B>\n";
                            }
                            boldOn = 0;
                        }
                        if (starOn > 0) {
                            for (int h = 0; h < starOn; h++) {
                                ret = ret + "</IL></UL>\n";
                            }
                        } else {
                            ret = ret + "<BR>\n";
                        }
                        if (i + 1 < text.length()) {
                            if (text.charAt(i + 1) == '\n') {
                                ret += "</UL>";
                            }
                        }

                        starOn = 0;
                        break;
                    case '{':
                        String block = "";
                        level = 0;
                        for (int j = i; j < text.length(); j++) {
                            if (text.charAt(j) == '{') {
                                level++;
                            } else if (text.charAt(j) == '}') {
                                level--;
                            }
                            block += text.charAt(j);
                            if (level == 0) {
                                citations.addElement(block);
                                i = j;
                                break;
                            }
                        }
                        break;

                    default:
                        ret += c;
                        controlOn = false;
                        break;

                }
            }

            // HACK
            do {
                ret = ret.replaceAll("<BR><BR><BR>", "<BR><BR>");
            } while (ret.indexOf("<BR><BR><BR>") != -1);
            do {
                ret = ret.replaceAll("<BR>\n<BR>\n<BR>\n", "<BR>\n<BR>\n");
            } while (ret.indexOf("<BR>\n<BR>\n<BR>\n") != -1);
            // HACK


            return ret;

        } catch (Exception ex) {
            System.out.println("tester parse:" + ex);
        }
        return "parse error";
    }

    public static String parseTitle(String t) {
        String ret = "";

        for (int i = 0; i < t.length(); i++) {
            if (t.charAt(i) != '=') {
                ret += t.charAt(i);
            }
        }
        ret = ret.trim();

        ret = ret.replaceAll("&amp;", "&");
        ret = ret.replaceAll("&apos;", "");
        ret = ret.replaceAll("&ndash;", "&");

        ret = ret.replaceAll("&GT;", ">");
        ret = ret.replaceAll("&gt;", ">");
        ret = ret.replaceAll("&LT;", "<");
        ret = ret.replaceAll("&lt;", "<");

        ret = ret.replaceAll("\\[\\[", "");
        ret = ret.replaceAll("\\]\\]", "");

        String sret = "";
        int count = 0;

        for (int i = 0; i < ret.length(); i++) {
            char c = ret.charAt(i);

            if (c == '<') {
                count++;
            } else if (c == '<') {
                count--;
            } else if (count == 0) {
                sret += c;
            }
        }

        return sret;
    }

    public static int parseLevel(String s) {
        try {
            int level = 0;

            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) == '=') {
                    level++;
                } else {
                    return level;
                }
            }
        } catch (Exception ex) {
            System.out.println(ex);
            ex.printStackTrace();
        }
        return 0;
    }
}
